/*****************************************************************************
 *
 * Weber State University
 * CS4280 Spring 2010
 * Final Group Assignment
 *
 *
 *   TTTTTT                               CCCCC
 *     TT   EEEEE   A    M   M          CC      C
 *     TT   E      A A   M   M         CC   
 *     TT   E     A   A  MM MM  -----  CC
 *     TT   EEE   AAAAA  M M M  -----  CC
 *     TT   E     A   A  M   M          CC      C
 *     TT   EEEEE A   A  M   M            CCCCC
 *
 *   Jared Pack ---- Jon Mann ---- Joshua Clayton
 *
 *
 * 
 *
 ****************************************************************************/

 /* FILENAME ogro.cpp
  *
  * Change control Section
  *
  * Team Member: Jon Mann
  * Version: 0.1
  * Date: 04/6/2010
  *     Added lighting code to OnPrepare() to light up the Sod model,
  *		but getting some strange lighting anomalies.
  *			**commented out until solved**
  *
  * Team Member: Jon Mann
  * Version: 0.2
  * Date: 04/9/2010
  *     Added aiState AI_ATTACK--enemy runs straight at player
  *		Added SetTerrain() and ReplaceDeadOgro() to respawn killed enemies
  *			and make them faster
  *      
  * Team Member: Jon Mann
  * Version: 0.3
  * Date: 04/13/2010
  *     Completely rebuilt dirToPlayer calculation in OnPepare() to 
  *			drastically improve enemy's ability to track player
  *		Minor reduction to respawned enemy's improved speed
  *		Moved the player-killing collision out of player.h and into here,
  *			it's more efficient and keeps a dead enemy from killing our hero
  */

#include "ogro.h"
// Phase 15 - Comment out the following
// Phase 16 - Uncomment
#include "rocket.h"
// Use the following temporarily
#include "player.h"

/*
	OGRO.CPP

	The COgroEnemy class implementation

	OpenGL Game Programming
	Author: Kevin Hawkins
	Date: 3/30/2001
	Description:

*/

void COgroEnemy::OnCollision(CObject *collisionObject)
{
	// as long as the model is not dying, it can collide with other objects
	if (modelState != MODEL_DIE)
	{
		// if this enemy collides with another enemy
		if ((typeid(*collisionObject) == typeid(CSodEnemy)) ||
			(typeid(*collisionObject) == typeid(COgroEnemy)))
		{
			aiState = AI_UNCARING;
		}
		else	if (typeid(*collisionObject) == typeid(CPlayer))
		{
			player->killPlayer();
		}
		// if this enemy collides with the terrain (always)
		else	if (typeid(*collisionObject) == typeid(CTerrain))
		{
			position.y = ((CTerrain*)collisionObject)->GetHeight(position.x, position.z) + size;
	
			if (position.x <= ((CTerrain*)collisionObject)->GetScanDepth())
				position.x = ((CTerrain*)collisionObject)->GetScanDepth();
			if (position.x >= ((CTerrain*)collisionObject)->GetWidth()*((CTerrain*)collisionObject)->GetMul() - ((CTerrain*)collisionObject)->GetScanDepth())
				position.x = ((CTerrain*)collisionObject)->GetWidth()*((CTerrain*)collisionObject)->GetMul() - ((CTerrain*)collisionObject)->GetScanDepth();
			if (position.z <= ((CTerrain*)collisionObject)->GetScanDepth())
				position.z = ((CTerrain*)collisionObject)->GetScanDepth();
			if (position.z >= ((CTerrain*)collisionObject)->GetWidth()*((CTerrain*)collisionObject)->GetMul() - ((CTerrain*)collisionObject)->GetScanDepth())
				position.z = ((CTerrain*)collisionObject)->GetWidth()*((CTerrain*)collisionObject)->GetMul() - ((CTerrain*)collisionObject)->GetScanDepth();
		}
		// Phase 15 - Comment out the following
		// Phase 16 - Uncomment
		else if (typeid(*collisionObject) == typeid(CRocket))
		{
			// kill the ogre
			aiState = AI_DEAD;
			//velocity = CVector(0.0, 0.0, 0.0);
		}
	}
}

void COgroEnemy::OnPrepare() 
{
	GLfloat lightIntensity[] = {0.8f, 0.8f, 0.8f, 1.0f}; // color and brightness
	glLightfv(GL_LIGHT2, GL_DIFFUSE, lightIntensity);
	//glEnable(GL_LIGHT2);
	// set the light source properties
	GLfloat light_position[] = {position.x, position.y, position.z, 1.0f};
	glLightfv(GL_LIGHT2, GL_POSITION, light_position); // location of light number 2, out of 8 possible lights

     float dirToPlayer;  // the angle of the enemy-player vector

     CVector diff;       // the vector from the enemy to the player
     diff.x = position.x - player->position.x;
     diff.z = position.z - player->position.z;
     diff.Normalize();

	 //***************** NEW *****************//
    // find the angle in the world of the vector from the enemy to the player
	// in relation the negative z-axis
	if ((diff.z > 0) && (diff.x > 0))
	{
		dirToPlayer = RAD2DEG(diff.Angle(CVector(0,0,-1)));
	}
	else if ((diff.z < 0) && (diff.x < 0))
	{
		dirToPlayer = (-1) * RAD2DEG(diff.Angle(CVector(0,0,-1)));
	}
	else if ((diff.z < 0) && (diff.x > 0))
	{
		dirToPlayer = 90 - RAD2DEG(diff.Angle(CVector(1,0,0)));
	}
	else if ((diff.z > 0) && (diff.x < 0))
	{
		dirToPlayer = 90 + RAD2DEG(diff.Angle(CVector(1,0,0)));
	}
	//***************** NEW *****************//

     // seed random generator
     srand((unsigned int)time(NULL));

     ProcessAI();
     // now do Ogro prep
     // set modelState based on AIstate
     switch (aiState)
     {
	 // this state makes the enemy very aggressive
	 case AI_ATTACK:
          direction = dirToPlayer + 90;         // set the direction of the enemy
		  // -90 to 90 degrees
			modelState = MODEL_RUN;
			velocity = CVector(0.0, 0.0, runSpeed);
          break;
     case AI_SCARED:
          direction = (dirToPlayer - 90) + ((rand()%90)-45);          // set the direction of the enemy
		  // -90 to 90 degrees
			modelState = MODEL_RUN;
			velocity = CVector(0.0, 0.0, 15.0);
          break;
     case AI_UNCARING:
          direction = float(rand() % 360);
          if ((rand() % 4) != 0)
          {
               modelState = MODEL_IDLE;
               velocity = CVector(0.0, 0.0, 0.0);
          }
          else
          {
              velocity = CVector(0.0, 0.0, 15.0);
              modelState = MODEL_RUN;
          }
          break;
     case AI_DEAD:
          modelState = MODEL_DIE;
          //velocity = CVector(0.0, 0.0, 0.0);
          if (nextFrame == stateStart)
          {
               // time to kill the monster
               isDead = true;
          }
		  if (canSpawn)
		  {
			player->RackUpAnotherKill(); // update our kill count
			ReplaceDeadOgro(); // let's build another
		  }
		  canSpawn = false;
          break;
     default:
          break;
     }

     // do prep for MD2 Model states
     CEntity::OnPrepare();
}

void COgroEnemy::Load()
{
	canSpawn = true;
	// load model
	CMD2Model::Load("models" FILE_SEP "ogro" FILE_SEP "tris.md2",
                        "models" FILE_SEP "ogro" FILE_SEP "ogrobase.pcx");
}

void COgroEnemy::OnProcessAI()
{
     // calculate distance from player
     CVector diff = player->position - position;

     if (aiState != AI_DEAD)
	{
		aiState = AI_ATTACK;
		/*
		distFromPlayer = sqrt(diff.x*diff.x + diff.y*diff.y + diff.z*diff.z);
		if (distFromPlayer < 125.0)
			aiState = AI_SCARED;
		else
			aiState = AI_UNCARING;
			*/
	}
}

// gives us access to the terrain for ReplaceDeadSod()
void COgroEnemy::SetTerrain(CTerrain *t)
{
	terrain = t;
}

// build a new ogro and place him randomly on the terrain
void COgroEnemy::ReplaceDeadOgro()
{
	COgroEnemy *ogroEnemy = new COgroEnemy(runSpeed + 5);
	ogroEnemy->AttachTo(terrain);
	ogroEnemy->SetPlayer(player);
	ogroEnemy->SetTerrain(terrain);
	// Phase 19 - Uncomment
#ifdef ENABLE_SOUND 
		ogroEnemy->SetAudioSystem(audioSystem);
#endif
	ogroEnemy->position.x = (float)(rand() % (int)(terrain->GetWidth() * terrain->GetMul()));
	ogroEnemy->position.y = 0.0f;
	ogroEnemy->position.z = (float)(rand() % (int)(terrain->GetWidth() * terrain->GetMul()));
}
